package com.gshappcore.persistence;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.jpa.JpaCallback;
import org.springframework.orm.jpa.support.JpaDaoSupport;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import java.lang.reflect.ParameterizedType;
import java.util.List;

public abstract class BasicRepository<K, E> extends JpaDaoSupport {

    protected Class<E> entityClass;

    @Autowired
    private EntityManagerFactory entityManagerFactory;


	@SuppressWarnings("unchecked")
	public BasicRepository() {
		ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
		this.entityClass = (Class<E>) genericSuperclass.getActualTypeArguments()[1];
	}

    @PostConstruct
    public void init() {
        super.setEntityManagerFactory(entityManagerFactory);
    }

	public void persist(E entity) {
		getJpaTemplate().persist(entity);
	}

	public void remove(E entity) {
		getJpaTemplate().remove(entity);
	}

	public E merge(E entity) {
		return getJpaTemplate().merge(entity);
	}

	public void refresh(E entity) {
		getJpaTemplate().refresh(entity);
	}

	public E findById(K id) {
		return getJpaTemplate().find(entityClass, id);
	}

	public E flush(E entity) {
		getJpaTemplate().flush();
		return entity;
	}

	@SuppressWarnings("unchecked")
	public List<E> findAll() {
		Object res = getJpaTemplate().execute(new JpaCallback() {
			public Object doInJpa(EntityManager em) throws PersistenceException {
				Query q = em.createQuery("SELECT h FROM " + entityClass.getName() + " h");
				return q.getResultList();
			}
		});
		return (List<E>) res;
	}

	@SuppressWarnings("unchecked")
	public Integer removeAll() {
		return (Integer) getJpaTemplate().execute(new JpaCallback() {
			public Object doInJpa(EntityManager em) throws PersistenceException {
				Query q = em.createQuery("DELETE FROM " + entityClass.getName() + " h");
				return q.executeUpdate();
			}
		});
	}

}
